use axum::{
  Router, debug_handler,
  extract::State,
  routing::{delete, get, post, put},
};
use sea_orm::{
  ActiveValue, Condition, IntoActiveModel, QueryOrder, QueryTrait, prelude::*,
};
use serde::Deserialize;
use validator::Validate;

use crate::{
  app::{
    AppState,
    common::{Page, PaginationParams},
    error::{ApiError, ApiResult},
    response::ApiResponse,
    utils::encode_password,
    ypath, yvalid,
  },
  entity::{
    company::{self, ActiveModel},
    prelude::*,
  },
};

#[derive(Debug, Deserialize, Validate)]
#[serde(rename_all = "camelCase")]
pub struct UserQueryParams {
  keyword: Option<String>,
  #[validate(nested)] // nested会深入到结构体中去校验
  #[serde(flatten)]
  pagination: PaginationParams,
}

pub type ApiResultResponse<T> = ApiResult<ApiResponse<T>>;

pub fn create_router() -> Router<AppState> {
  Router::new()
    .route("/", get(find_page))
    .route("/", post(create_company))
    .route("/{id}", put(update_company))
    .route("/{id}", delete(delete_company))
  // 0.8 该的路径参数语法,从/:single和/*many更改为/{single}和/{*many}
}

/// curl http://127.0.0.1:3000/api/users\?page\=1\&size\=10\&keyword\=xx -X GET -H "Content-Type: application/json" -H "Authorization: Bearer xx_token"
/// curl http://127.0.0.1:3000/api/users\?page\=1\&size\=10\&keyword\=x -X GET
#[debug_handler]
async fn find_page(
  State(AppState { db }): State<AppState>,
  // 不使用axum的Query,和Valid,使用自定义的了
  yvalid::ValidQuery(UserQueryParams {
    keyword,
    pagination,
  }): yvalid::ValidQuery<UserQueryParams>,
) -> ApiResultResponse<Page<company::Model>> {
  let paginator = Company::find()
    .apply_if(keyword.as_ref(), |query, keyword| {
      query.filter(
        Condition::any()
          .add(company::Column::Name.contains(keyword))
          .add(company::Column::Address.contains(keyword)),
      )
    })
    // .order_by_desc(company::Column::Age)
    .order_by_asc(company::Column::Age)
    .paginate(&db, pagination.size);
  let total = paginator.num_items().await?;
  let items = paginator.fetch_page(pagination.page - 1).await?;

  let page = Page::from_pagination(pagination, total, items);
  Ok(ApiResponse::ok("ok", Some(page)))
}

#[derive(Debug, Deserialize, Validate, DeriveIntoActiveModel)]
pub struct Companyparams {
  #[validate(length(min = 1, max = 16, message = "姓名长度1 - 16"))]
  pub name: String,
  pub age: i32,
  #[validate(length(min = 1, max = 16, message = "姓名长度1 - 16"))]
  #[validate(custom(
    function = "crate::app::yvalidation::is_mobile_phone",
    message = "xxxxx格式不对"
  ))]
  pub address: String,
  pub salary: Option<f32>,
  pub join_date: Date,
  #[serde(default)]
  pub enabled: bool,
}

/// curl http://127.0.0.1:3000/api/users -X POST -H "Content-Type: application/json" -d '{"name":"timly","age": 103,"address":"13967331234","salary":12340.0,"join_date":"2025-11-01","enabled":true}'
#[debug_handler]
async fn create_company(
  State(AppState { db }): State<AppState>,
  yvalid::ValidJson(params): yvalid::ValidJson<Companyparams>,
) -> ApiResultResponse<company::Model> {
  println!(">>>>> {:?}", params);
  let mut active_model = params.into_active_model();

  let addr = active_model.address.unwrap().unwrap();
  active_model.address = ActiveValue::Set(Some(encode_password(&addr)?));
  let result = active_model.insert(&db).await?;

  Ok(ApiResponse::ok("ok", Some(result)))
}

/// curl http://127.0.0.1:3000/api/users/1 -X PUT -H "Content-Type: application/json" -d '{"name":"jsonxxxxxx","age": 10,"address":"13963446713","salary":11.0,"join_date":"2026-10-22","enabled":true}'
#[debug_handler]
async fn update_company(
  State(AppState { db }): State<AppState>,
  ypath::Path(id): ypath::Path<String>,
  yvalid::ValidJson(params): yvalid::ValidJson<Companyparams>,
) -> ApiResultResponse<company::Model> {
  /*
        let existed_user = Company::find_by_id(&id)
          .one(&db)
          .await?
          .ok_or_else(|| ApiError::Biz("需要修改的用户不存在".to_string()))?;
        let password = params.address.clone();
        let mut active_model = params.into_active_model();

        active_model.id = ActiveValue::Unchanged(existed_user.id);

        if password.is_empty() {
          active_model.address = ActiveValue::Unchanged(existed_user.address);
        } else {
          let addr = active_model.address.unwrap().unwrap();
          active_model.address =
            ActiveValue::Set(Some(bcrypt::hash(addr, bcrypt::DEFAULT_COST)?));
        }

        let result = active_model.update(&db).await?;

        Ok(ApiResponse::ok("ok", Some(result)))
  */

  let existed_user = Company::find_by_id(&id)
    .one(&db)
    .await?
    .ok_or_else(|| ApiError::Biz("需要修改的用户不存在".to_string()))?;

  let old_password = existed_user.address.clone();
  let password = params.address.clone();
  let mut existed_active_model = existed_user.into_active_model();
  let mut active_model = params.into_active_model();
  existed_active_model.clone_from(&active_model);

  existed_active_model.id = ActiveValue::Unchanged(id);
  if password.is_empty() {
    // Unchanged 表示不修改
    active_model.address = ActiveValue::Unchanged(old_password);
  } else {
    let addr = active_model.address.unwrap().unwrap();
    active_model.address = ActiveValue::Set(Some(encode_password(&addr)?));
  }

  let result = existed_active_model.update(&db).await?;

  Ok(ApiResponse::ok("ok", Some(result)))
}

/// curl http://127.0.0.1:3000/api/users/1 -X DELETE
#[debug_handler]
async fn delete_company(
  State(AppState { db }): State<AppState>,
  ypath::Path(id): ypath::Path<String>,
) -> ApiResultResponse<()> {
  let existed_user = Company::find_by_id(&id)
    .one(&db)
    .await?
    .ok_or_else(|| ApiError::Biz("需要修改的用户不存在".to_string()))?;

  let result = existed_user.delete(&db).await?;
  tracing::info!(
    "Deleted user: {}, arrected rows: {}",
    id,
    result.rows_affected
  );
  Ok(ApiResponse::ok("ok", None))
}
